package com.flyqiu.flow.core;

import com.flyqiu.common.bean.FlyQiuBeanManage;
import com.flyqiu.common.tools.FlyQiuCollectionTools;
import com.flyqiu.flow.api.FlyQiuFlowConfig;
import com.flyqiu.flow.api.cache.FlyQiuFlowCacheManage;
import com.flyqiu.flow.api.context.FlyQiuFlowGlobalContext;
import com.flyqiu.flow.api.service.*;
import com.flyqiu.flow.api.service.base.FlowCommentService;
import com.flyqiu.flow.api.service.base.FlowVariableService;
import com.flyqiu.flow.api.service.hi.FlowHiVariableService;
import com.flyqiu.flow.api.service.hi.HiIdentityLinkService;
import com.flyqiu.flow.api.service.ru.FlowRuVariableService;
import com.flyqiu.flow.api.service.ru.RuIdentityLinkService;
import com.flyqiu.flow.core.cache.DefaultFlyQiuFlowLocalCache;
import com.flyqiu.flow.core.impl.*;
import com.flyqiu.flow.core.impl.base.FlowCommentServiceImpl;
import com.flyqiu.flow.core.impl.hi.FlowHiVariableServiceImpl;
import com.flyqiu.flow.core.impl.hi.HiIdentityLinkServiceImpl;
import com.flyqiu.flow.core.impl.ru.FlowRuActivityServiceImpl;
import com.flyqiu.flow.core.impl.ru.FlowRuUserTaskServiceImpl;
import com.flyqiu.flow.core.impl.ru.FlowRuVariableServiceImpl;
import com.flyqiu.flow.core.impl.ru.RuIdentityLinkServiceImpl;
import com.flyqiu.flow.mapper.CommentMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.transaction.TransactionFactory;
import org.mybatis.spring.transaction.SpringManagedTransactionFactory;

import javax.sql.DataSource;

/**
 * 默认流程引擎实现
 */
@Slf4j
public class DefaultFlyQiuFlowEngineImpl extends BaseFlowEngineImpl {

    // mapper包
    public static final String FLY_QIU_FLOW_MAPPER = "com.flyqiu.flow.mapper";


    public DefaultFlyQiuFlowEngineImpl(DataSource dataSource) {
        this(dataSource, new SpringManagedTransactionFactory());

    }

    public DefaultFlyQiuFlowEngineImpl(DataSource dataSource, TransactionFactory transactionFactory) {
        globalContext = DefaultFlyQiuFlowGlobalContext.create(dataSource, transactionFactory);
    }

    protected <T> T autoAddBean(Class<T> clazz, T bean) {
        FlyQiuBeanManage beanManage = globalContext.getBeanManage();
        log.info("自动获取bean:" + clazz.getName());
        if (beanManage.hasBean(clazz)) {
            return beanManage.getBean(clazz);
        }
        beanManage.addBean(clazz, bean);
        return bean;
    }

    @Override
    protected FlyQiuFlowCacheManage initFlowCacheManage(FlyQiuFlowGlobalContext globalContext, FlyQiuFlowConfig procConfig) {
        FlyQiuFlowCacheManage flyQiuFlowCacheManage = super.initFlowCacheManage(globalContext, procConfig);
        if (FlyQiuCollectionTools.isEmpty(procConfig.getProcCaches())) {
            flyQiuFlowCacheManage.registerCache(new DefaultFlyQiuFlowLocalCache());
        }
        return flyQiuFlowCacheManage;
    }


    @Override
    protected void initCoreService() {
        FlyQiuBeanManage procBean = globalContext.getBeanManage();

        modelService = autoAddBean(FlowModelService.class, new FlowModelServiceImpl(globalContext));

        FlowRuVariableServiceImpl flowRuVariableService = new FlowRuVariableServiceImpl(globalContext);
        autoAddBean(FlowRuVariableService.class, flowRuVariableService);
        FlowHiVariableServiceImpl flowHiVariableService = new FlowHiVariableServiceImpl(globalContext);
        autoAddBean(FlowHiVariableService.class, flowHiVariableService);
        FlowVariableServiceImpl flowVariableService = new FlowVariableServiceImpl(globalContext, flowRuVariableService, flowHiVariableService);
        autoAddBean(FlowVariableService.class, flowVariableService);


        autoAddBean(FlowRuActivityService.class, new FlowRuActivityServiceImpl(globalContext));

        HiIdentityLinkServiceImpl hiIdentityLinkService = new HiIdentityLinkServiceImpl(globalContext);
        autoAddBean(HiIdentityLinkService.class, hiIdentityLinkService);
        RuIdentityLinkServiceImpl ruIdentityLinkService = new RuIdentityLinkServiceImpl(globalContext);
        autoAddBean(RuIdentityLinkService.class, ruIdentityLinkService);
        IdentityLinkServiceImpl identityLinkService = new IdentityLinkServiceImpl(globalContext, ruIdentityLinkService, hiIdentityLinkService);
        autoAddBean(IdentityLinkService.class, identityLinkService);


        autoAddBean(FlowRuUserTaskService.class, new FlowRuUserTaskServiceImpl(globalContext));
        FlowCommentServiceImpl flowCommentService = new FlowCommentServiceImpl(procBean.getMapper(CommentMapper.class));
        autoAddBean(FlowCommentService.class, flowCommentService);


        flowTaskService = new FlowTaskServiceImpl(globalContext, flowCommentService, identityLinkService, flowVariableService);
        flowTaskService = autoAddBean(FlowTaskService.class, flowTaskService);

        flowRunningService = new FlowRunningServiceImpl(globalContext, flowCommentService, identityLinkService, flowVariableService);
        flowRunningService = autoAddBean(FlowRunningService.class, flowRunningService);

        flowHistoryService = new FlowHistoryServiceImpl(globalContext, flowCommentService, identityLinkService, flowVariableService);
        flowHistoryService = autoAddBean(FlowHistoryService.class, flowHistoryService);

    }


}
